---
title: 프레임워크 컴포넌트
description: React, Svelte 등을 사용하는 방법을 배웁니다.
i18nReady: true
---
import IntegrationsNav from '~/components/IntegrationsNav.astro'
import ReadMore from '~/components/ReadMore.astro'

선호하는 컴포넌트 프레임워크를 희생하지 않고 Astro 웹사이트를 구축하세요. 선택한 UI 프레임워크를 사용하여 Astro [아일랜드](/ko/concepts/islands/)을 만드세요.

## 공식 UI 프레임워크 통합

Astro는 [React](https://ko.react.dev/), [Preact](https://preactjs.com/), [Svelte](https://svelte.dev/), [Vue](https://ko.vuejs.org/), [SolidJS](https://www.solidjs.com/), [AlpineJS](https://alpinejs.dev/), [Lit](https://lit.dev/) 공식 통합이 포함되어 있습니다.

통합 디렉터리에서 더 많은 [커뮤니티에서 관리하는 프레임워크 통합](https://astro.build/integrations/?search=&categories%5B%5D=frameworks) (예: Angular, Qwik, Elm)을 찾아보세요.

<IntegrationsNav category="renderer" />

## 통합 설치

이러한 Astro 통합 중 하나 이상을 프로젝트에 설치하고 구성할 수 있습니다.

Astro 통합 설치 및 구성에 대한 자세한 내용은 [통합 안내서](/ko/guides/integrations-guide/)를 참조하세요.

:::tip
선택한 프레임워크의 예시를 보고 싶으십니까? [astro.new](https://astro.new/latest/frameworks)를 방문하여 프레임워크 템플릿 중 하나를 선택하세요.
:::

## 프레임워크 컴포넌트 사용하기

Astro 컴포넌트와 마찬가지로 자바스크립트 프레임워크 컴포넌트를 Astro 페이지, 레이아웃, 컴포넌트에서 사용할 수 있습니다! 모든 컴포넌트는 `/src/components`에 모아두거나 원하는 대로 구성할 수 있습니다.

프레임워크 컴포넌트를 사용하려면 Astro 컴포넌트 스크립트에서 상대 경로를 지정하여 가져옵니다. 그리고 컴포넌트 템플릿에서 다른 컴포넌트, HTML 요소, JSX와 같은 표현식과 함께 사용합니다.

```astro title="src/pages/static-components.astro" ins={2,7}
---
import MyReactComponent from '../components/MyReactComponent.jsx';
---
<html>
  <body>
    <h1>Astro 안에서 React 컴포넌트를 직접 사용하세요!</h1>
    <MyReactComponent />
  </body>
</html>
```

기본적으로 프레임워크 컴포넌트는 서버에서 정적 HTML로 렌더링 됩니다. 이는 비대화형 컴포넌트를 템플릿화하는데 유용하며, 필요하지 않은 자바스크립트를 클라이언트에 전송하는 것을 방지합니다.


## 인터랙티브 컴포넌트 하이드레이션하기

프레임워크 컴포넌트는 [`client:*` 지시어](/ko/reference/directives-reference/#클라이언트-지시어)를 이용하여 대화형(하이드레이션)으로 만들 수 있습니다. 이는 컴포넌트의 자바스크립트가 브라우저로 전송되는 시기를 결정하는 컴포넌트 속성입니다.

`client:only`를 제외한 모든 클라이언트 지시어를 사용하면 컴포넌트는 먼저 서버에서 렌더링 되어 정적 HTML을 생성합니다. 자바스크립트 컴포넌트는 지시어에 따라 브라우저로 전송됩니다. 이후 컴포넌트가 하이드레이트 되어 인터랙티브하게 됩니다.

```astro title="src/pages/interactive-components.astro" /client:\S+/
---
// 예: 브라우저에서 컴포넌트 하이드레이션하기
import InteractiveButton from '../components/InteractiveButton.jsx';
import InteractiveCounter from '../components/InteractiveCounter.jsx';
import InteractiveModal from "../components/InteractiveModal.svelte"
---
<!-- 이 컴포넌트의 자바스크립트는 페이지 로딩 시에 가져옵니다. -->
<InteractiveButton client:load />

<!-- 이 컴포넌트의 자바스크립트는 사용자가 스크롤하여 컴포넌트가 페이지에 표시될 때까지 클라이언트에게 전송되지 않습니다. -->
<InteractiveCounter client:visible />

<!-- 이 컴포넌트는 서버에서 렌더링되지 않고 페이지 로딩 시 클라이언트에서 렌더링됩니다. -->
<InteractiveModal client:only="svelte" />
```

컴포넌트를 렌더링하는 데 필요한 자바스크립트 프레임워크(React, Svelte 등)는 컴포넌트 자체의 자바스크립트와 함께 브라우저로 전송됩니다. 페이지의 여러 컴포넌트가 동일한 프레임워크를 사용하는 경우, 프레임워크는 한 번만 전송됩니다.

:::note[접근성]
이 컴포넌트들을 Astro 에서 사용할 경우, 프레임워크별 접근성 패턴이 동일하게 작동해야 합니다. 접근성 관련 자바스크립트가 제대로 로드되고 실행되도록 클라이언트 지시어를 반드시 설정해야 합니다.
:::

### 사용 가능한 하이드레이션 지시어

UI 프레임워크 컴포넌트에서 사용할 수 있는 하이드레이션 지시어는 `client:load`, `client:idle`, `client:visible`, `client:media={QUERY}`, `client:only={FRAMEWORK}`입니다.

<ReadMore>하이드레이션 지시어에 대한 자세한 설명과 사용법은 [지시어 참조](/ko/reference/directives-reference/#클라이언트-지시어) 페이지를 참조하세요.</ReadMore>

## 프레임워크 혼합하기

동일한 Astro 컴포넌트 내에서 여러 프레임워크에서 만든 컴포넌트를 가져와 렌더링할 수 있습니다.

```astro title="src/pages/mixing-frameworks.astro"
---
// 예: 한 페이지에 여러 프레임워크의 구성요소를 혼합하는 경우
import MyReactComponent from '../components/MyReactComponent.jsx';
import MySvelteComponent from '../components/MySvelteComponent.svelte';
import MyVueComponent from '../components/MyVueComponent.vue';
---
<div>
  <MySvelteComponent />
  <MyReactComponent />
  <MyVueComponent />
</div>
```

:::caution
**Astro** 컴포넌트(`.astro`)만 여러 프레임워크의 컴포넌트를 포함할 수 있습니다.
:::

## 프레임워크 컴포넌트에 Props 전달하기

Astro 컴포넌트에서 프레임워크 컴포넌트로 props를 전달할 수 있습니다.

```astro title="src/pages/frameworks-props.astro"
---
import TodoList from '../components/TodoList.jsx';
import Counter from '../components/Counter.svelte';
---
<div>
  <TodoList initialTodos={["learn Astro", "review PRs"]} />
  <Counter startingCount={1} />
</div>
```

:::caution[함수를 props로 전달하기]
프레임워크 컴포넌트에 함수를 프로퍼티로 전달할 수 있지만, 이 함수는 서버 렌더링 중에만 작동합니다. 이 함수를 하이드레이션 컴포넌트(예: 이벤트 핸들러)에서 사용하려고 하면 오류가 발생합니다.

이는 Astro 에서 함수를 직렬화(서버에서 클라이언트로 전송)할 수 없기 때문입니다.
:::


## 프레임워크 컴포넌트에 자식 요소 전달하기

Astro 컴포넌트에서는 프레임워크 컴포넌트에 자식 요소를 전달할 수 있습니다. 각 프레임워크마다 이러한 자식 요소를 참조하는 고유한 패턴이 있는데, React, Preact, Solid는 `children`이라는 특별한 속성을 사용하고, Svelte와 Vue는 `<slot />`라는 요소를 사용합니다.

```astro title="src/pages/component-children.astro" {5}
---
import MyReactSidebar from '../components/MyReactSidebar.jsx';
---
<MyReactSidebar>
  <p>텍스트와 버튼이 있는 사이드바입니다.</p>
</MyReactSidebar>
```

또한, [명명된 슬롯](/ko/basics/astro-components/#명명된-슬롯)을 사용하여 특정 하위 요소를 그룹화할 수 있습니다.

React, Preact, Solid에서 이러한 슬롯은 최상위 속성으로 변환되며, `kebab-case`를 사용하는 슬롯 이름은 `camelCase`로 변환됩니다.

```astro title="src/pages/named-slots.astro" /slot="(.*)"/
---
import MySidebar from '../components/MySidebar.jsx';
---
<MySidebar>
  <h2 slot="title">Menu</h2>
  <p>텍스트와 버튼이 있는 사이드바입니다.</p>
  <ul slot="social-links">
    <li><a href="https://twitter.com/astrodotbuild">Twitter</a></li>
    <li><a href="https://github.com/withastro">GitHub</a></li>
  </ul>
</MySidebar>
```

```jsx /{props.(title|socialLinks)}/
// src/components/MySidebar.jsx
export default function MySidebar(props) {
  return (
    <aside>
      <header>{props.title}</header>
      <main>{props.children}</main>
      <footer>{props.socialLinks}</footer>
    </aside>
  )
}
```

Svelte와 Vue에서 이러한 슬롯은 `<slot>` 요소에 `name` 속성을 붙여 참조할 수 있습니다. 또한 `kebab-case`를 사용한 슬롯 이름은 그대로 유지됩니다.

```jsx /slot name="(.*)"/
// src/components/MySidebar.svelte
<aside>
  <header><slot name="title" /></header>
  <main><slot /></main>
  <footer><slot name="social-links" /></footer>
</aside>
```

## 프레임워크 컴포넌트 중첩하기

Astro 파일 내에서는 프레임워크 컴포넌트의 자식 요소도 하이드레이션된 컴포넌트로 만들 수 있습니다. 즉, 프레임워크의 모든 컴포넌트를 재귀적으로 중첩할 수 있습니다.

```astro title="src/pages/nested-components.astro" {10-11}
---
import MyReactSidebar from '../components/MyReactSidebar.jsx';
import MyReactButton from '../components/MyReactButton.jsx';
import MySvelteButton from '../components/MySvelteButton.svelte';
---

<MyReactSidebar>
  <p>텍스트와 버튼이 있는 사이드바입니다.</p>
  <div slot="actions">
    <MyReactButton client:idle />
    <MySvelteButton client:idle />
  </div>
</MyReactSidebar>
```

:::caution
프레임워크의 컴포넌트 자체(예: `.jsx`, `.svelte`)는 여러 프레임워크를 혼용할 수 없습니다.
:::

이를 통해 원하는 자바스크립트 프레임워크로 전체 '앱'을 구축하고 상위 컴포넌트를 통해 Astro의 페이지로 렌더링할 수 있습니다.

:::note
Astro 컴포넌트는 하이드레이션되는 프레임워크 컴포넌트를 포함하더라도 항상 정적 HTML로 렌더링 됩니다. 즉, Astro 컴포넌트에서 프레임워크 컴포넌트에 React의 'render props'를 전달하면, Astro 컴포넌트는 이 패턴이 요구하는 클라이언트 런타임 동작을 제공하지 못하기 때문에 작동하지 않습니다. 대신 이름을 가진 슬롯을 사용합니다.
:::

## 프레임워크 컴포넌트 중 Astro 컴포넌트를 사용할 수 있나요?

UI 프레임워크 컴포넌트는 해당 프레임워크의 '아일랜드 (섬)'가 됩니다. 이러한 컴포넌트는 해당 프레임워크의 유효한 코드로서 자체 가져오기 또는 패키지를 사용하여 완전히 작성해야 하며, UI 프레임워크 컴포넌트(예: `.jsx` 또는 `.svelte`) 내에서 .astro 컴포넌트를 가져올 수 없습니다.

하지만 [Astro의 `<slot />` 패턴](/ko/basics/astro-components/#슬롯)을 이용하여 Astro 컴포넌트가 생성한 정적 콘텐츠를 **.astro 컴포넌트 내에서** 프레임워크 컴포넌트에 자식 요소로 전달할 수 있습니다.

```astro title="src/pages/astro-children.astro" {6}
---
import MyReactComponent from  '../components/MyReactComponent.jsx';
import MyAstroComponent from '../components/MyAstroComponent.astro';
---
<MyReactComponent>
  <MyAstroComponent slot="name" />
</MyReactComponent>
```

## Astro 컴포넌트에 하이드레이션을 할 수 있나요?

`client:` 지시어를 사용하여 Astro 컴포넌트에 하이드레이션을 시도하면 오류가 발생합니다.

[Astro 컴포넌트](/ko/basics/astro-components/)는 클라이언트 측 런타임이 없는 HTML 전용 템플릿 컴포넌트입니다. 하지만 Astro 컴포넌트 템플릿에서 `<script>` 태그를 사용하여 브라우저 전역 범위에서 실행되는 자바스크립트를 보낼 수 있습니다.

<ReadMore>[Astro 컴포넌트의 클라이언트 측 `<script>` 태그](/ko/guides/client-side-scripts/) 대해 자세히 알아보기</ReadMore>

[mdn-io]: https://developer.mozilla.org/ko/docs/Web/API/Intersection_Observer_API
[mdn-ric]: https://developer.mozilla.org/ko/docs/Web/API/Window/requestIdleCallback
[mdn-mm]: https://developer.mozilla.org/ko/docs/Web/API/Window/matchMedia
